package com.boot.system.service.impl;

import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.cron.CronUtil;
import cn.hutool.cron.task.Task;
import com.boot.common.constant.GlobalVar;
import com.boot.common.result.Result;
import com.boot.system.entity.SysJob;
import com.boot.system.mapper.JobMapper;
import com.boot.system.service.JobService;
import com.boot.util.ConvertUtil;
import com.boot.util.SecurityUtil;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@RequiredArgsConstructor
@Service("jobService")
public class JobServiceImpl extends ServiceImpl<JobMapper, SysJob> implements JobService {

    @Override
    public Page<SysJob> getJobPage(Map<String, Object> queryParam) {
        // 基础参数
        int pageNum = (int) queryParam.getOrDefault("pageNum", 1);
        int pageSize = (int) queryParam.getOrDefault("pageSize", 10);
        Page<SysJob> page = new Page<>(pageNum, pageSize);
        // 查询条件
        QueryWrapper query = QueryWrapper.create().from(SysJob.class);
        // 模糊查询
        query.and(q -> q.and(SysJob::getName).like(queryParam.get("keywords"))
                        .or(SysJob::getClassPath).like(queryParam.get("keywords"))
                        .or(SysJob::getRemark).like(queryParam.get("keywords")),
                ObjectUtil.isNotEmpty(queryParam.get("keywords")));
        if (ObjectUtil.isNotEmpty(queryParam.get("status"))) {
            // 状态
            query.eq("status", queryParam.get("status"));
        }
        query.orderBy((String) queryParam.getOrDefault("orderBy", "update_time desc, id desc"));
        return this.page(page, query);
    }

    @Override
    public List<SysJob> getJobList(Map<String, Object> queryParam) {
        QueryWrapper query = QueryWrapper.create().from(SysJob.class);
        if (ObjectUtil.isNotEmpty(queryParam.get("status"))) {
            // 状态
            query.eq("status", queryParam.get("status"));
        }
        query.orderBy((String) queryParam.getOrDefault("orderBy", "update_time desc, id desc"));
        return this.list(query);
    }

    @Override
    public Result<?> addJob(Map<String, Object> dataParam) {
        SysJob sysJob = ConvertUtil.mapToClass(dataParam, SysJob.class);
        sysJob.setStatus(0);
        sysJob.setCreateBy(SecurityUtil.getUid());
        sysJob.setCreateTime(GlobalVar.systemTime);
        sysJob.setUpdateBy(SecurityUtil.getUid());
        sysJob.setUpdateTime(GlobalVar.systemTime);
        return Result.success(this.save(sysJob));
    }

    @Override
    public Result<?> updateJob(Map<String, Object> dataParam) {
        SysJob sysJob = ConvertUtil.mapToClass(dataParam, SysJob.class);
        //检查任务是否在执行（执行中的任务不能修改）
        SysJob task = this.getById(sysJob.getId());
        if (task != null && task.getStatus() == 1){
            return Result.success(false);
        }
        if (task != null) {
            //不能修改状态
            sysJob.setStatus(task.getStatus());
        }
        sysJob.setUpdateBy(SecurityUtil.getUid());
        sysJob.setUpdateTime(GlobalVar.systemTime);
        return Result.success(this.updateById(sysJob));
    }

    @Override
    public boolean deleteJob(String ids) {
        List<Long> idList = Arrays.stream(ids.split(","))
                .map(Long::parseLong)
                .collect(Collectors.toList());
        //检查是否有执行中的任务（执行中的任务不能删除）
        QueryWrapper query = QueryWrapper.create().from(SysJob.class);
        query.eq("status", 1);
        query.in("id", idList);
        if (this.count(query) > 0){
            return false;
        }
        return this.removeByIds(idList);
    }

    @Override
    public SysJob getJobById(Long id) {
        return this.getById(id);
    }

    @Override
    public void runJob(SysJob task) {
        try {
            // 加载类
            Class<?> clazz = ClassUtil.loadClass(task.getClassPath());
            // 创建类的实例
            Object instance = clazz.getDeclaredConstructor().newInstance();
            // 获取方法对象
            Method method = clazz.getMethod("execute");
            // 调用方法
            method.invoke(instance);
        } catch (Exception e) {
            log.error("任务:【{}】执行失败,原因:【{}】", task.getName(), e.getCause().getMessage());
        }
    }

    @Override
    public boolean startJob(Long id) {
        SysJob task = getJobById(id);
        if (task != null){
            CronUtil.schedule(StrUtil.format("task{}", task.getId()), task.getCron(), new Task() {
                @Override
                public void execute() {
                    runJob(task);
                }
            });
            task.setStatus(1);
            this.updateById(task);
            return true;
        }
        return false;
    }

    @Override
    public boolean stopJob(Long id) {
        SysJob task = getJobById(id);
        if (task != null){
            CronUtil.remove(StrUtil.format("task{}", task.getId()));
            task.setStatus(0);
            this.updateById(task);
            return true;
        }
        return false;
    }
}
